package gruppe5.dame.client.gui.game;

import gruppe5.dame.client.Ressourcen;
import gruppe5.dame.model.DameModel;
import gruppe5.dame.model.Pawn;
import gruppe5.dame.model.types.DameGameType;
import gruppe5.dame.model.types.PawnDirection;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.util.List;

import javax.swing.JLabel;
import javax.swing.JPanel;

/**
 * Spielfeld des Damespiels
 * Zug zwang wird nicht angezeigt
 * 
 * @author kramerse
 * 
 */
public class Spielfeld extends JPanel {

	/**
	 * serialVersionUID
	 */
	private static final long serialVersionUID = 7739288062025555741L;
	/**
	 * Spielfeld
	 */
	private JLabel[][] feld;

	/**
	 * aktuell makierter Stein
	 * (1,-1) -> kein Stein makiert
	 */
	Dimension makierterStein = new Dimension(-1, -1);

	/**
	 * Spielsteine
	 */
	private Pawn[][] steine;

	/**
	 * Spielfeld Listener
	 */
	private ListenerSpielfeld listener = new ListenerSpielfeld(this);

	/**
	 * Liste mit verf�gbaren Z�gen
	 */
	private List<PawnDirection> list;
	
	/**
	 * aktuell makierter Pawn
	 */
	private Pawn makierterPawn;
	
	/**
	 * Spieler m&ouml;chte in diese Richtung ziehen
	 */
	private PawnDirection wunschRichtung;
	
	/**
	 * UI Element Dame
	 */
	private DameGUI dameGui;
	
//	/**
//	 * Dame Model Spiellogik
//	 */
//	private DameModel model;

	/**
	 * Konstruktor (10x10 Feld)
	 * 
	 * @param dameGUI
	 */
	public Spielfeld(DameGUI dameGUI) {
		this.dameGui = dameGUI;
//		this.model = dameGui.getModel();
		this.setLayout(new GridLayout(dameGui.getGridSize(), dameGui.getGridSize()));
		this.feld = new JLabel[dameGui.getGridSize()][dameGui.getGridSize()];
		erzeugeFeld(dameGUI.getGridSize());
		addFeld();
	}

	/**
	 * F&uuml;gt die Felder zum UI Element hinzu.
	 */
	private void addFeld() {
		for (int i = 0; i < feld.length; i++)
			for (int j = 0; j < feld.length; j++) {
				feld[i][j].addMouseListener(listener);
				this.add(feld[i][j]);
			}
//		updateSteine();
	}

	/**
	 * Erzeugt die Felder f&uuml;r das UI Element.
	 * 
	 * @param size
	 */
	private void erzeugeFeld(int size) {
		if (size == 8 || size == 10 || size == 12) {
			for (int i = 0; i < size; i++) {
				for (int j = 0; j < size; j++) {
					if ((i + j) / 2 == ((double) i + (double) j) / 2)
						feld[i][j] = erzeugeLabelWeis();
					else
						feld[i][j] = erzeugeLabelSchwarz();
				}
			}
		}
	}

	/**
	 * Erzeugt ein Label mit schwarzem Hintergrund und wei&szlig;er Schriftfarbe
	 * 
	 * @return
	 */
	private JLabel erzeugeLabelSchwarz() {
		JLabel label = new JLabel();
		label.setForeground(new Color(255, 255, 255));
		label.setOpaque(true);
		label.setBackground(Color.DARK_GRAY);
		label.setPreferredSize(new Dimension(50, 50));
		return label;
	}

	/**
	 * Erzeugt ein Label mit wei&szlig;em Hintergrund
	 * 
	 * @return
	 */
	private JLabel erzeugeLabelWeis() {
		JLabel label = new JLabel();
		label.setOpaque(true);
		label.setBackground(new Color(255, 255, 255));
		label.setPreferredSize(new Dimension(50, 50));
		return label;
	}

	
	public void updateSteine(Pawn[] pawns) {
		
		this.steine = new Pawn[dameGui.getGridSize()][dameGui.getGridSize()];
		for(Pawn pawn : pawns)
		{
			this.steine[pawn.getX()][pawn.getY()] = pawn;
		}
		
		updateSteine();
	}
	
	
	
	
	/**
	 * Erneuert die Positionen der Steine auf dem Spielfeld
	 * 
	 * @param steine
	 */
	public void updateSteine() {

		Ressourcen.updateIcons(82, 70);
		
		
		if (feld.length == steine.length) {
			for (int i = 0; i < feld.length; i++)
				for (int j = 0; j < feld.length; j++) {

					
					feld[i][j].setIcon(null);
					
					try {
						if (steine[i][j].isBlack()) {
							feld[i][j].setIcon(Ressourcen.getBlackPawn());
							if (steine[i][j].isDame())
								feld[i][j].setIcon(Ressourcen.getBlackDame());
						} else {
							feld[i][j].setIcon(Ressourcen.getWhitePawn());
							if (steine[i][j].isDame())
								feld[i][j].setIcon(Ressourcen.getWhiteDame());
						}
					} catch (Exception e) {
					}
				}
		}
		revalidate();
		update(this.getGraphics());
	}

	/**
	 * Hebt ein Feld hervor
	 * 
	 * @param i
	 * @param j
	 */
	public void feldHervorheben(int i, int j) {
		if ((i + j) / 2 == ((double) i + (double) j) / 2) {
			feld[i][j].setBackground(new Color(255, 150, 75));
		} else {
			feld[i][j].setBackground(new Color(255, 50, 25));
		}
		revalidate();
	}

	/**
	 * Entfernt die Hervorhebung eines Feldes
	 * 
	 * @param i
	 * @param j
	 */
	public void feldEnthervorheben(int i, int j) {
		if ((i + j) / 2 == ((double) i + (double) j) / 2) {
			feld[i][j].setBackground(new Color(255, 255, 255));
		} else {
			feld[i][j].setBackground(new Color(0, 0, 0));
		}
		if (makierterStein.getHeight() != -1)
			feldHervorheben((int) makierterStein.getHeight(),
					(int) makierterStein.getWidth());
		revalidate();
	}

	/**
	 * Entfernt die Hervorhebung aller Felder
	 * 
	 * @param i
	 * @param j
	 */
	public void feldEnthervorheben() {
		for (int i = 0; i < dameGui.getGridSize(); i++) {
			for (int j = 0; j < dameGui.getGridSize(); j++) {
				if ((i + j) / 2 == ((double) i + (double) j) / 2)
					feld[i][j].setBackground(new Color(255, 255, 255));
				else
					feld[i][j].setBackground(new Color(0, 0, 0));
			}
		}
		if (makierterStein.getHeight() != -1)
			steinHervorheben((int) makierterStein.getHeight(),
					(int) makierterStein.getWidth());
		revalidate();
	}

	/**
	 * Hebt ein Feld hervor
	 * 
	 * @param label
	 */
	public void hervorheben(JLabel label) {
		for (int i = 0; i < feld.length; i++)
			for (int j = 0; j < feld.length; j++) {
				if (label == feld[i][j])
					if (makierterStein.height == -1)
						steinHervorheben(i, j);
			}

	}

	/**
	 * hebt ein Stein und dessen m�gliche Z�ge hervor
	 * 
	 * @param i
	 * @param j
	 */
	public void steinHervorheben(int i, int j) {
		felderEnthervorheben();
		if(i == -1){
			if(makierterStein.height != -1)
			steinHervorheben(makierterStein.height, makierterStein.width);
			return;
		}
		feldHervorheben(i, j);
		try {
			list = steine[i][j].getAvailableMoves();
		} catch (Exception e) {
			System.err.println("Keine Bewegung moeglich... @" + i + " " + j);
			return;
		}

		for (int k = 0; k < list.size(); k++) {
			switch (list.get(k)) {
			case BOTTOM_RIGHT:
				feldHervorheben(i + 1, j + 1);
				break;
			case TOP_RIGHT:
				feldHervorheben(i - 1, j + 1);
				break;
			case BOTTOM_LEFT:
				feldHervorheben(i + 1, j - 1);
				break;
			case TOP_LEFT:
				feldHervorheben(i - 1, j - 1);
				break;
			case DOUBLE_BOTTOM_RIGHT:
				feldHervorheben(i + 2, j + 2);
				break;
			case DOUBLE_TOP_RIGHT:
				feldHervorheben(i + 2, j - 2);
				break;
			case DOUBLE_BOTTOM_LEFT:
				feldHervorheben(i - 2, j + 2);
				break;
			case DOUBLE_TOP_LEFT:
				feldHervorheben(i - 2, j - 2);
				break;
			default:
				break;
			}
		}
	}

	private void felderEnthervorheben() {
		for (int i = 0; i < dameGui.getGridSize(); i++) {
			for (int j = 0; j < dameGui.getGridSize(); j++) {
				if ((i + j) / 2 == ((double) i + (double) j) / 2)
					feld[i][j].setBackground(new Color(255, 255, 255));
				else
					feld[i][j].setBackground(Color.DARK_GRAY);
			}
		}
	}

	/**
	 * entfert hervorhebung
	 * 
	 * @param label
	 */
	public void hervorhebungentfernen(JLabel label) {
		for (int i = 0; i < feld.length; i++)
			for (int j = 0; j < feld.length; j++) {
				if (label == feld[i][j])
					feldEnthervorheben();
			}
	}

	/**
	 * Label wurde geklickt
	 * 
	 * @param label
	 */
	public void klicked(JLabel label) {
		for (int i = 0; i < feld.length; i++) {
			for (int j = 0; j < feld.length; j++) {
				if(label == feld[i][j]) { // geklicktes Label gefunden
					if(steine[i][j] != null)
						makierterPawn = steine[i][j];
						
					try {
						list = makierterPawn.getAvailableMoves(); // moegliche zuege des aktuell makierten steins
					} catch (Exception e) {
						System.err.println("Keine Bewegung moeglich @" + i + " " + j);
					}
					if(moeglicherZug(i, j)) { //TODO will der Spieler ziehen
						dameGui.movePawn(makierterPawn.getId(), wunschRichtung);
						makierterPawn = null;
					} else { //makierung entfernen
						if(i == makierterStein.getHeight() || j == makierterStein.getWidth())
							makierterStein.setSize(-1, -1);
						else { //oder makierung setzten
							makierterStein.setSize(j, i);
							steinHervorheben(i, j);
						}
					}
				}
			}
		}
	}

	/**
	 * Ist auf das Feld ein Zug m&ouml;glich
	 * @param i
	 * @param j
	 * @return true = ja
	 */
	private boolean moeglicherZug(int i, int j) {

				try {
					list = makierterPawn.getAvailableMoves();
				} catch (Exception e) {
					return false;
				}

				for (int k = 0; k < list.size(); k++) {
					switch (list.get(k)) {
					case BOTTOM_RIGHT:
						if(i + 1 == makierterStein.getHeight() && j + 1 == makierterStein.getWidth());
						wunschRichtung = PawnDirection.BOTTOM_RIGHT;
						return true;
					case TOP_RIGHT:
						if(i + 1 == makierterStein.getHeight() && j - 1 == makierterStein.getWidth());
						wunschRichtung = PawnDirection.TOP_RIGHT;
						return true;
					case BOTTOM_LEFT:
						if(i - 1 == makierterStein.getHeight() && j + 1 == makierterStein.getWidth());
						wunschRichtung = PawnDirection.BOTTOM_LEFT;
						return true;
					case TOP_LEFT:
						if(i - 1 == makierterStein.getHeight() && j - 1 == makierterStein.getWidth());
						wunschRichtung = PawnDirection.TOP_LEFT;
						return true;
					case DOUBLE_BOTTOM_RIGHT:
						if(i + 2 == makierterStein.getHeight() && j + 2 == makierterStein.getWidth());
						wunschRichtung = PawnDirection.DOUBLE_BOTTOM_RIGHT;
						return true;
					case DOUBLE_TOP_RIGHT:
						if(i + 2 == makierterStein.getHeight() && j - 2 == makierterStein.getWidth());
						wunschRichtung = PawnDirection.DOUBLE_TOP_RIGHT;
						return true;
					case DOUBLE_BOTTOM_LEFT:
						if(i - 2 == makierterStein.getHeight() && j + 2 == makierterStein.getWidth());
						wunschRichtung = PawnDirection.DOUBLE_BOTTOM_LEFT;
						return true;
					case DOUBLE_TOP_LEFT:
						if(i - 2 == makierterStein.getHeight() && j - 2 == makierterStein.getWidth());
						wunschRichtung = PawnDirection.DOUBLE_TOP_LEFT;
						return true;
					default:
						wunschRichtung = null;
						return false;
					}
				}
		return false;
	}
	
	////////////////////////////////////////////////////
	///////////TEST
	////////////////////////////////////////////////////
	
	public JLabel checkedLabelTEST;
	
	public Pawn checkedPawnTEST;

	public void hervorhebenTEST(JLabel label) 
	{
		if(label == checkedLabelTEST)
			return;
		
		for (int i = 0; i < feld.length; i++)
		{
			for (int j = 0; j < feld.length; j++) 
			{
				if (label == feld[i][j])
				{
					if ((i + j) / 2 == ((double) i + (double) j) / 2) 
					{
						feld[i][j].setBackground(new Color(255, 150, 75));
					} else {
						feld[i][j].setBackground(new Color(255, 50, 25));
					}
				}
					
			}
		}
	}
	
	public void entHervorhebenTEST(JLabel label) 
	{
		if(label == checkedLabelTEST)
			return;
		
		for (int i = 0; i < feld.length; i++)
		{
			for (int j = 0; j < feld.length; j++) 
			{
				if (label == feld[i][j])
				{
					if ((i + j) / 2 == ((double) i + (double) j) / 2) 
					{
						feld[i][j].setBackground(Color.WHITE);
					} else {
						feld[i][j].setBackground(Color.DARK_GRAY);
					}
				}
					
			}
		}
	}

	public void klickedTEST(JLabel label) 
	{
		for (int i = 0; i < feld.length; i++)
		{
			for (int j = 0; j < feld.length; j++) 
			{
				if(label == feld[i][j])
				{
					if(checkedPawnTEST != null)
					{
						dameGui.movePawn(checkedPawnTEST.getId(), PawnDirection.TOP_LEFT);
						System.out.println("checkedPawnTEST != null");
						PawnDirection direction = isValidDirectionForCheckedPawnTEST(i, j);
						if(direction != null)
						{
							System.out.println("direction != null");
							dameGui.movePawn(checkedPawnTEST.getId(), direction);
						}
						entHervorhebenTEST(checkedLabelTEST);
						checkedPawnTEST = null;
						checkedLabelTEST = null;
						return;
					}
					if((steine[i][j] == null) || (steine[i][j] == checkedPawnTEST))
					{
						checkedPawnTEST = null;
						checkedLabelTEST = null;
					} else {
						checkedPawnTEST = steine[i][j];
						checkedLabelTEST = label;
					}
				}
			}
		}		
	}
	
	private PawnDirection isValidDirectionForCheckedPawnTEST(int i, int j) {

		try {
			list = makierterPawn.getAvailableMoves();
		} catch (Exception e) {
			return null;
		}
		
		int pawn_i = checkedPawnTEST.getX();
		int pawn_j = checkedPawnTEST.getY();
		

		for (int k = 0; k < list.size(); k++) {
			switch (list.get(k)) {
			case BOTTOM_RIGHT:
				if(i + 1 == pawn_i && j + 1 == pawn_j);
				return PawnDirection.BOTTOM_RIGHT;
			case TOP_RIGHT:
				if(i + 1 == pawn_i && j - 1 == pawn_j);
				return PawnDirection.TOP_RIGHT;
			case BOTTOM_LEFT:
				if(i - 1 == pawn_i && j + 1 == pawn_j);
				return PawnDirection.BOTTOM_LEFT;
			case TOP_LEFT:
				if(i - 1 == pawn_i && j - 1 == pawn_j);
				return PawnDirection.TOP_LEFT;
			case DOUBLE_BOTTOM_RIGHT:
				if(i + 2 == pawn_i && j + 2 == pawn_j);
				return PawnDirection.DOUBLE_BOTTOM_RIGHT;
			case DOUBLE_TOP_RIGHT:
				if(i + 2 == pawn_i && j - 2 == pawn_j);
				return PawnDirection.DOUBLE_TOP_RIGHT;
			case DOUBLE_BOTTOM_LEFT:
				if(i - 2 == pawn_i && j + 2 == pawn_j);
				return PawnDirection.DOUBLE_BOTTOM_LEFT;
			case DOUBLE_TOP_LEFT:
				if(i - 2 == pawn_i && j - 2 == pawn_j);
				return PawnDirection.DOUBLE_TOP_LEFT;
			default:
				return null;
			}
		}
	return null;
	}
	
}